前幾天我們已經學會抓 API 資料並進行分析,但很多實際應用中的 API 都需要金鑰(API Key)。
因此,今天我要挑戰的是申請一把 API Key ,並學會安全管理避免金鑰外洩。
API Key 是一組像密碼一樣的字串,用來辨識每個使用 API 的人。
需要 API Key 的原因:
API 金鑰的作用就是要先確認使用的人有註冊過,這樣可以避免陌生人亂用服務。它還能限制每個人使用的次數或速度,避免有人一直狂用把系統弄壞。另外,平台也能透過金鑰記錄大家的使用情況,方便做用量統計或收費。
今天我的目標是成功申請並啟動 OpenWeatherMap (簡稱 OWM)的 API 金鑰,接著學習如何安全地存放金鑰而不是直接寫在程式碼裡,然後用 Python 呼叫 OWM 的天氣服務,顯示自己選擇的城市的溫度和天氣情況,同時也要了解金鑰管理的重要性,避免發生錯誤。
步驟 0:環境準備
pip install requests python-dotenv
用 Python 的 requests 套件可以幫助我們發送像瀏覽器一樣的網路請求,讓我們向網站或 API 取得資料。
python-dotenv 這個工具可以幫我們從一個叫做 .env
的檔案中,安全讀取我們儲存的秘密資訊,比如 API 金鑰。讓程式在執行時,不用把金鑰直接寫在程式碼裡。
步驟 1:註冊並拿到 API 金鑰
到 OpenWeatherMap 網站註冊帳號。
登入後去 API keys 頁面,複製預設的金鑰。
需要先等幾分鐘,才能讓金鑰正式啟用。
步驟 2:安全存放金鑰
在專案資料夾裡,新增一個叫做 .env
的檔案。
把金鑰寫成這樣:
OWM_API_KEY=我的金鑰
我們需要在 .gitignore
檔案裡加上 .env
,這樣才不會把金鑰上傳到 GitHub。
.env
程式裡用 os.environ.get("OWM_API_KEY")
讀金鑰,不能直接在程式碼寫金鑰。
步驟 3:練習一個測試金鑰的程式
用 API 查詢台北市的天氣。
把地點、溫度和天氣狀況印出來。
import os
import requests
API = "https://api.openweathermap.org/data/2.5/weather"
定義一個常數 API:OpenWeatherMap 的現在天氣端點網址。
def main():
api_key = os.environ.get("OWM_API_KEY") # 從環境變數取金鑰
if not api_key:
print("找不到 OWM_API_KEY。請在 .env 或系統環境變數設定。")
return
params = { # 要送到 API 的查詢參數
"q": "Taipei", # 城市名(也可用 lat/lon)
"appid": api_key, # 金鑰
"units": "metric", # 攝氏
"lang": "zh_tw", # 回傳中文描述
}
try:
r = requests.get(API, params=params, timeout=10)
r.raise_for_status()
data = r.json()
except requests.exceptions.RequestException as e:
print("API 失敗:", e)
return
# 取出常見欄位
name = data.get("name")
main = (data.get("main") or {})
weather0 = (data.get("weather") or [{}])[0]
temp = main.get("temp")
desc = weather0.get("description")
print(f" {name} | {temp}°C | {desc}")
if __name__ == "__main__":
main()
執行結果:
Taipei 現在 29.84°C,晴
步驟 4:做更安全的程式
使用 dotenv.load_dotenv()
從 .env
載入金鑰並做好錯誤處理,且在印出結果時只顯示遮蔽後的金鑰以避免洩漏。
import os
import requests
from dotenv import load_dotenv
API = "https://api.openweathermap.org/data/2.5/weather"
def mask(key: str) -> str:
if not key: return ""
if len(key) <= 6: return "*" * len(key)
return key[:3] + "*" * (len(key)-6) + key[-3:]
def get_weather_by_city(city: str, units="metric", lang="zh_tw", timeout=10):
load_dotenv() # 讀取 .env(若有)
api_key = os.environ.get("OWM_API_KEY")
if not api_key:
raise RuntimeError("找不到 OWM_API_KEY(請在 .env 或環境變數設定)")
mask()
:把金鑰遮罩,避免把完整金鑰印出來get_weather_by_city()
:讀 .env
拿金鑰,沒有就報錯
params = { # #要送到 API 的查詢參數
"q": city,
"appid": api_key,
"units": units,
"lang": lang,
}
try:
r = requests.get(API, params=params, timeout=timeout)
# 常見錯誤處理
if r.status_code == 401:
raise RuntimeError("401 未授權:API Key 無效或未啟用。")
if r.status_code == 404:
raise RuntimeError(f"404 找不到城市:{city}")
if r.status_code == 429:
raise RuntimeError("429 達到呼叫上限,請稍後再試。")
r.raise_for_status()
return r.json()
except requests.exceptions.Timeout:
raise RuntimeError("連線逾時,網路可能不穩或伺服器忙碌。")
except requests.exceptions.ConnectionError:
raise RuntimeError("連線錯誤,請檢查網路或防火牆設定。")
except requests.exceptions.HTTPError as e:
raise RuntimeError(f"HTTP 錯誤:{e}")
def format_weather(data: dict) -> str:
name = data.get("name") or "-"
main = (data.get("main") or {})
weather0 = (data.get("weather") or [{}])[0]
temp = main.get("temp")
feels = main.get("feels_like")
desc = weather0.get("description") or "-"
return f" {name}\n 氣溫:{temp}°C(體感 {feels}°C)\n 天氣:{desc}"
if __name__ == "__main__":
city = "Taipei"
try:
data = get_weather_by_city(city)
print(format_weather(data))
except RuntimeError as e:
# 不要在錯誤訊息中印出完整金鑰
key = os.environ.get("OWM_API_KEY")
print("發生錯誤:", e)
if key:
print("(提示)目前使用的金鑰:", mask(key))
執行結果:
Taipei
氣溫:29.56°C(體感 33.99°C)
天氣:晴,少雲
不要直接寫在程式碼裡
把 API 金鑰直接寫在程式碼中很危險,因為程式碼可能會被別人看到。安全做法是把金鑰放在專門的設定檔,像是 .env
文件裡,再讓程式讀取。
使用 .gitignore
保護金鑰
如果我們用 Git 來管理程式碼,要在 .gitignore
檔裡寫上 .env
,這樣這個檔案就不會被推送到 GitHub,避免別人看到金鑰。
不要把金鑰放在前端程式裡
前端像是 JavaScript 或 HTML 的程式碼是開放給使用者看到的,不能放敏感的金鑰。API 金鑰應該只放在後端程式中,確保安全。
定期更換金鑰
為了減少風險,我們最好定期把 API 金鑰換掉。這樣如果有人偷到我們的金鑰,它也不會一直有效。
金鑰外洩時要快速處理
如果不小心把金鑰外洩了,要馬上到服務平台撤銷那個金鑰,然後換一組新的,防止別人濫用我們的 API。
401 Unauthorized(未授權)
這表示輸入的 API 金鑰錯誤或還沒啟用。要先檢查金鑰是不是打錯字,或者剛申請的金鑰還沒生效,等幾分鐘後再試。
404 Not Found(找不到資源)
這通常是因為輸入的城市名稱拼錯了。可以改用更穩定的經緯度(latitude、longitude)來查詢天氣,這樣比較不會出錯。
429 Too Many Requests(請求過多)
表示對 API 的使用次數太多,超出平台限制。解決方法是減少呼叫頻率,或是將取得的資料暫存(快取)起來,避免重複請求。
Timeout / Connection Error(連線逾時或錯誤)
代表網路不穩或伺服器太忙沒有回應。可以在程式設定等待時間,遇到這種錯誤時重試幾次,避免程式直接崩潰。
今天我完成了申請 OpenWeatherMap 的 API Key,並學會如何把金鑰安全地存放與在程式中正確呼叫,同時更加理解金鑰管理的重要性與常見錯誤的成因與處理方式。未來使用其他需要金鑰的 API 時,我也能沿用這套流程,降低風險並提升開發效率。